package com.jf3q.admin.service.impl;

import com.jf3q.admin.excel.SubjectData;
import com.jf3q.admin.excel.SubjectDataListener;
import com.jf3q.admin.service.EduSubjectService;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jf3q.common.domain.EduSubject;
import com.jf3q.common.exception.JfException;
import com.jf3q.common.mapper.EduSubjectMapper;
import com.jf3q.common.vo.SubjectVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 */
@Service
@Slf4j
public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject>
    implements EduSubjectService {


    @Override
    public void importExcel(MultipartFile file) {

        //读取excel文件  用easyExcel
        //1 获取文件输入流
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
            // 这里 需要指定读用哪个class去读，然后读取第一个sheet 文件流会自动关闭
            EasyExcel.read(inputStream, SubjectData.class, new SubjectDataListener(this)).sheet().doRead();

        } catch (IOException e) {
            e.printStackTrace();
            throw new JfException(20002,"添加课程分类失败");
        }


    }

    @Override
    public void saveFromExcel(List<SubjectData> cachedDataList) {//优化后的尽量少查数据库

        //开始把从excel中读取到的数据保存到数据库
        if (ObjectUtils.isEmpty(cachedDataList)) {
            throw new JfException(20001, "文件数据为空");
        }
        //把cachedDataList封装成map

        // 0  服务端开发  java
        // 1  服务端开发  python
        Map<String, List<String>> map = new HashMap<>();

        for (SubjectData subjectData : cachedDataList) {
            List<String> li = map.get(subjectData.getOneSubjectName());
            if (li == null) li = new ArrayList<>();
            li.add(subjectData.getTwoSubjectName());
            map.put(subjectData.getOneSubjectName(), li);

        }
        //为了减少查询语句  实际开发用的非常多
        List<EduSubject> subjects = this.list();
        Map<String ,EduSubject> existMap = new HashMap<>();
        for (EduSubject o : subjects) {
            existMap.put(o.getTitle(),o);
        }
        map.forEach((one,twoLi)-> {
            EduSubject existOneSubject=  existMap.get(one);// 导入的excel的一级分类在数据库里是否存在
            if(existOneSubject==null){
                //保存一级目录
                existOneSubject=new EduSubject();
                existOneSubject.setTitle( one);
                existOneSubject.setParentId("0");//主键回调  就能拿到主键id
                this.save(existOneSubject);

            }
            // 备注：如果一级目录已经存在的话只保存二级目录即可

            List<EduSubject> twoSubjects= new ArrayList<>(); //为了后面批量保存
            for (String title : twoLi) {
                EduSubject existTwoSubject = existMap.get(title);//导入的excel的二级分类在数据库里是否存在
                if(existTwoSubject == null){ //判断二级目录去重
                    existTwoSubject = new EduSubject();
                    existTwoSubject.setTitle(title);
                    existTwoSubject.setParentId(existOneSubject.getId());
                    twoSubjects.add(existTwoSubject);
                }

            }
            //批量保存二级目录
            this.saveBatch(twoSubjects);

        });
    }

    /**
     * //其实有很多查询的方式
     * 1.先查询出一级分类然后循环查二级分类set进去。这种是笨办法，sql语句多
     * 2.自关联查询
     * 3.递归查询（性能最好）
     * @return
     */
    @Override
    public List<SubjectVo> getAllSubject() {
        List<SubjectVo> vos= new ArrayList<>();
        List<EduSubject> list = this.list();//查询所有的分类
        for (EduSubject eduSubject : list) {
            SubjectVo subjectVo = new SubjectVo();
            BeanUtils.copyProperties(eduSubject,subjectVo);
            vos.add(subjectVo);
        }

        //vos  数据库有几条分类数据就有几个 ，二级和一级全都混合在一起
        //递归的方式查   一直自查 直到查不到数据为止
        List<SubjectVo> subjectVos = new ArrayList<>();

        for (SubjectVo treeNode : vos) {
            if ("0".equals(treeNode.getParentId())) {//说明是一级分类
                subjectVos.add(findChildren(treeNode,vos));//就要装填二级分类
            }
        }
        return subjectVos;
    }

    /**
     * 递归查找子节点   自己调用自己
     * @param treeNodes
     * @return
     */
    public static SubjectVo findChildren( SubjectVo subject,List<SubjectVo> treeNodes) {
        subject.setChildren(new ArrayList<>());

        for (SubjectVo it : treeNodes) {
            if(subject.getId().equals(it.getParentId())) {
//                subject.getChildren().add(findChildren(it,treeNodes));//把二级分类挂在一级上面(也可以是三级挂在二级上面以此类推)
                subject.getChildren().add(it);//把二级分类挂在一级上面
                findChildren(it,treeNodes);//根据二级找三级，根据三级找四级，以此类推
            }
        }

        System.out.println(subject.getChildren());
        return subject;
    }

}




